package com.ds.common.org.expression.person;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

import com.ds.common.expression.ParseException;
import com.ds.common.expression.function.Function;
import com.ds.org.Person;
import com.ds.org.Role;

/**
 * 使用工作组过滤人员
 * <p>
 * Title: JDSORG组织机构中间件
 * </p>
 * <p>
 * Description:
 * </p>
 * <p>
 * Copyright: jds Copyright (c) 2003-2008
 * </p>
 * <p>
 * Company: www.justdos.net
 * </p>
 * 
 * @author wenzhangli
 * @version 2.0
 */
public class FilterPersonByPersonGroup extends Function {
    public FilterPersonByPersonGroup() {
	numberOfParameters = 2;
    }

    public void run(Stack stack) throws ParseException {
	checkStack(stack); // check the stack

	Object param2 = stack.pop();
	Object param1 = stack.pop();
	stack.push(perform(param1, param2));
    }

    protected Person[] perform(Object param1, Object param2) throws ParseException {
	if (param1 == null) {
	    return new Person[0];
	}
	if (param1 instanceof Person[] && param2 == null) {
	    return (Person[]) param1;
	}

	// PersonGroup数组
	if (param1 instanceof Person[] && param2 instanceof Role[]) {
	    Person[] persons = (Person[]) param1;
	    Role[] groups = (Role[]) param2;
	    int m = groups.length;
	    if (m == 0) {
		return persons;
	    }

	    List result = new ArrayList();
	    for (int i = 0; i < m; i++) {
		if (groups[i] == null) {
		    continue;
		}
		Person[] ps = screening(groups[i], persons);
		for (int j = 0; j < ps.length; j++) {
		    if (!result.contains(ps[j])) {
			result.add(ps[j]);
		    }
		}
	    }
	    for (int i = 0; i < m; i++) {
		if (groups[i] == null) {
		    continue;
		}
		persons = screening(groups[i], persons);
	    }

	    return (Person[]) result.toArray(new Person[result.size()]);
	}

	// PersonGroup
	if (param1 instanceof Person[] && param2 instanceof Role) {
	    Person[] persons = (Person[]) param1;
	    Role group = (Role) param2;

	    return screening(group, persons);
	}

	throw new ParseException("Invalid parameter type in:" + this.getClass().getName() + ", param1 is " + param1.getClass().getName() + ", param2 is " + param2.getClass().getName());
    }

    public Person[] screening(Role role, Person[] persons) {
	List result = new ArrayList();
	for (int i = 0; i < persons.length; i++) {
	    Person p = persons[i];
	    if (role.getPersonIdList().contains(p.getID())) {
		result.add(p);
	    }
	}
	return (Person[]) result.toArray(new Person[result.size()]);
    }
}
